#include <fstream>
#include <iostream>
#include <regex>
#include <string>
#include <array>
#include <list>

#define MAXWEEK 23

struct dateInf
{
    int startWeek;
    int endWeek;
    bool isSeries;
};

struct classInf
{
    std::string Name;
    std::string teacher;
    std::string classroom;
    std::list<dateInf> dateList;
    int daySchedule;
};

class asError
{
    public:
        asError(std::string m1,std::string m2) :
            errReason(m1),
            errString(m2)
        {}
        std::string errReason;
        std::string errString;
};

classInf analyString(std::string itemData)
{
    classInf newInf;
    std::smatch m;
    bool isFound=std::regex_search(itemData,m,std::regex(R"((.*)/(.*)/(.*)/(.*)/(.*))"));
    if(isFound)
    {
        newInf.Name=m[1].str();

        std::string classTime=m[2].str();
        auto CTstartPos=classTime.cbegin();
        auto CTendPos=classTime.cend();
        std::smatch m1;
        std::regex reg(R"(([0-9]+-)?([0-9]+)周)");
        for(;std::regex_search(CTstartPos,CTendPos,m1,std::regex(R"(([0-9]+-)?([0-9]+)周)"));CTstartPos=m1.suffix().first)
        {
            std::cout<<'\t';
            dateInf newDateInf={};
            if(m1[1].str().size()==0)
            {
                newDateInf.endWeek=newDateInf.startWeek=std::atoi(m1[2].str().c_str());
                newDateInf.isSeries=false;
            }
            else
            {
                auto ac=m1[1].str();
                ac.pop_back();
                newDateInf.startWeek=std::atoi(ac.c_str());
                newDateInf.endWeek=std::atoi(m1[2].str().c_str());
                auto nc=m1.suffix().first;
                if(nc!=CTendPos && *nc=='(')
                    newDateInf.isSeries=false;
                else
                    newDateInf.isSeries=true;
            }
            newInf.dateList.push_back(newDateInf);
        }

        std::string classIndex=m[3].str();
        if(std::regex_search(classIndex,m1,std::regex(R"([0-9]?-[0-9]{3})")))
            newInf.classroom=m1[0].str();
        else
            throw asError("教室匹配失败",m[3].str());

        newInf.teacher=m[4].str();
    }
    else
        throw asError("字符串匹配失败",itemData);

    return newInf;
}

int main()
{
    std::array<std::list<classInf>,40> weekSchedule;
    std::ifstream iFileData("data.txt");
    if(!iFileData.is_open())
    {
        std::cerr<<"文件打开失败: data.txt"<<std::endl;
        return -1;
    }

    //读取文件
    char readChar={};
    int countRow=0;
    int countColumn=0;
    std::string readItem;
    auto arrItr=weekSchedule.begin();
    int classCount=1;
    while (iFileData.get(readChar) && arrItr!=weekSchedule.end())
    {
        if(readChar=='\t' || readChar=='\n')
        {
            if(readItem.size()!=0)
            {
                try
                {
                    if(readChar=='\n')
                        classCount++;
                    auto newInf=analyString(readItem);
                    newInf.daySchedule=classCount;
                    arrItr->push_back(newInf);
                }
                catch(const asError& e)
                {
                    std::cerr<<"解析错误"<<std::endl;
                    std::cerr<<"\t错误原因: "<<e.errReason<<std::endl;
                    std::cerr<<"\t错误语句: "<<e.errString<<std::endl;
                }
            }
            arrItr++;
            readItem.clear();
            continue;
        }
        if(readChar=='"')
        {
            while (iFileData.get(readChar))
            {
                if(readChar=='"')
                    break;
                if(readChar=='\n')
                {
                    try
                    {
                        auto newInf=analyString(readItem);
                        arrItr->push_back(newInf);
                    }
                    catch(const asError& e)
                    {
                        std::cerr<<"解析错误"<<std::endl;
                        std::cerr<<"\t错误原因: "<<e.errReason<<std::endl;
                        std::cerr<<"\t错误语句: "<<e.errString<<std::endl;
                    }
                    
                    readItem.clear();
                    continue;
                }
                readItem.push_back(readChar);
            }
            continue;
        }
        readItem.push_back(readChar);
    }
    iFileData.close();
    std::cout<<"一天最大课程数: "<<classCount<<std::endl;

    std::array<std::list<classInf>,MAXWEEK*5> arrCalendar={};
    arrItr=weekSchedule.begin();
    for(int i=0;i<8;i++)   //day
    {
        if(arrItr==weekSchedule.end())
            break;
        for(int j=0;j<5;j++)    //week
        {
            for(classInf k:*arrItr)
            {
                for(dateInf l:k.dateList)
                {
                    int addNum=0;
                    if(l.isSeries)
                        addNum=1;
                    else
                        addNum=2;
                    for(int m=l.startWeek;m<=l.endWeek;m+=addNum)
                    {
                        arrCalendar.at((m-1)*5+j).push_back(k);
                    }
                }
            }
            arrItr++;
        }
    }

    std::ofstream oFile;
    auto DebugCheekPoint=[&](int a,std::ofstream& oFile)
    {
        for(auto i:arrCalendar.at(a))
        {
            oFile<<"\t第"<<i.daySchedule<<"节课"<<std::endl;
            oFile<<"\t\t课程名称: "<<i.Name<<std::endl;
            oFile<<"\t\t授课老师: "<<i.teacher<<std::endl;
            oFile<<"\t\t上课地点: "<<i.classroom<<std::endl;
        }   
    };

    char FileName[100];
    for(int i=0;i<MAXWEEK;i++)
    {
        std::sprintf(FileName,"week%d.txt",i+1);
        oFile.open(FileName,std::ios::trunc);
        if(!oFile.is_open())
        {
            std::cerr<<"文件新建失败: "<<FileName<<std::endl;
            return -1;
        }
        oFile<<"第"<<i+1<<"周"<<std::endl;
        oFile<<std::endl;
        for(int j=0;j<5;j++)
        {
            oFile<<"第"<<j+1<<"天"<<std::endl;
            DebugCheekPoint(i*5+j,oFile);
        }
        oFile.close();
    }

    return 0;
}